﻿using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Text;

namespace TreeLayoutPlayground
{
    class SimpleLayoutEngine : LayoutEngine
    {
        public SimpleLayoutEngine() { }

        public override void Layout(Tree tree)
        {
            tree.MyRelativeTranslation = Size.Empty;
            tree.MyBox.X = 0;
            tree.MyBox.Y = 0;

            if (tree.NumberOfChildren == 0)
            {
                tree.OverallSize = tree.MyBox.Size;
                return;
            }

            // Layout the children sequentially
            // A child's leftmost point is its left neighbor's rightmost point
            // plus gapsize
            int top = tree.MyBox.Height + GapSize;
            int left = 0;
            foreach (Tree c in tree.Children)
            {
                Layout(c);
                c.MyRelativeTranslation.Width = left;
                c.MyRelativeTranslation.Height = top;
                left += GapSize + c.OverallSize.Width;
            }

            // Center myself in the overall image area
            // Make sure that none of my children would be out of bounds
            left -= GapSize;
            if (left < tree.MyBox.Width)
            {
                int diff = (tree.MyBox.Width - left) / 2;
                foreach (Tree c in tree.Children)
                {
                    c.MyRelativeTranslation.Width += diff;
                }

                left = 0;
            }
            else
            {
                left = (left / 2) - (tree.MyBox.Width / 2);
            }

            tree.MyBox.X = left;

            // Find the size of the area that my children take up
            // Sum all the widths and find the max height
            Size chSize = tree.Children.Aggregate(new Size(),
                (acc, t) =>
                {
                    Size c = t.OverallSize;
                    return new Size(
                        acc.Width + c.Width,
                        Math.Max(acc.Height, c.Height));
                });

            // Add my own size to the child area as well as the gap space size for each child
            tree.OverallSize = new Size(
                1 + Math.Max(tree.MyBox.Width, (chSize.Width + ((tree.NumberOfChildren - 1) * GapSize))),
                1 + tree.MyBox.Height + chSize.Height + GapSize);
        }
    }
}
